/*
 * SvrClient.cpp
 *
 *  Created on: 2012-7-11
 *      Author: ThinkPad
 */
#include "SvrClient.h"

SvrClient::SvrClient(void)
{
    count = 0;
    connid = 0;
    SessionTick = 0;
    this->pSvrconfig = NULL;
    this->pSvrtask = NULL;
    this->pSvrlog = NULL;
}

SvrClient::~SvrClient(void)
{
    /*add your code here*/
}

/*
 * init server client
 */
int SvrClient::init(SvrConfig * pconfig,SvrTask * psvrtask,Svr_log * psvrlog,SvrFileManage * psvrfilemanage,int init_size)
{
    if(pconfig == NULL
    		||psvrtask == NULL
    		||psvrlog == NULL
    		||psvrfilemanage == NULL)
        return FAILURE;

    this->pSvrconfig = pconfig;
    this->pSvrtask = psvrtask;
    this->pSvrlog = psvrlog;
    this->pSvrFileUtils = psvrfilemanage;

    /*
    *alloc client token
    */
    for(int i = 0 ;i < init_size;i++)
    {
        user_token * token = NULL;
        token = new user_token();
        if(token != NULL)
        {
            client_pool.push(token);
            count++;
        }
    }

    /*init server session pool*/
    if(this->sessionMgr.init() != SUCCESS)
    {
        return FAILURE;
    }

    return SUCCESS;
}

/*
*token pool operation
*/
void SvrClient::alloc(user_token ** client)
{
    pool_lock.Lock();
    {
        if(client_pool.size() >0 )
        {
             *client = client_pool.top();
             client_pool.pop();
        }
        else
        {
             *client = new user_token();
             count++;
        }
        /*init*/
        (*client)->tConnTime = time(NULL);
        (*client)->timeConnBegin = time(NULL);
        /*end*/
        pool_lock.Unlock();
    }
}

void SvrClient::free(user_token * client)
{
    pool_lock.Lock();
    {
        if(client != NULL)
        {
              client->id = 0;
              client->type = 0;
              client->index = 0;
              memset(client->key,'\0',sizeof(client->key));

              client->offset = 0;
              client->length = 0;
              client->count = 0;
              client->trans_size = 0;
              client->have_trans_size = 0;
              client->last_size = 0;

              if(client->filefd >= 0)
              {
                  close(client->filefd);
                  client->filefd = -1;
              }
              client->hFile_size = 0;
              client->hFile_offset = 0;

              client->send_timeout = 0;
              client->receive_timeout = 0;
              client->trans_file_timeout = 0;
              client->tConnTime = time(NULL);
              client->timeConnBegin = time(NULL);
              client->connectionFlag = 0;
              client->recv_send_flag = FALSE;
              client->conn_index = 0;
              client->privt = NULL;

              client_pool.push(client);
        }
        pool_lock.Unlock();
    }
}

int SvrClient::get_free_count()
{
    return (int)client_pool.size();
}

int SvrClient::get_count()
{
     return count;
}

/*
*session manager
*/
int SvrClient::get_session_count()
{
     return this->sessionMgr.get_session_count();
}

/*
*session manager
*/
int SvrClient::get_free_session_count()
{
    return this->sessionMgr.get_free_session_count();
}

/*
*session manager
*/
AUTH_STATUS SvrClient::get_client_session_auth_status(const char * key)
{
    return sessionMgr.find_session_auth_status(key);
}

/*
*session manager
*/
bool SvrClient::set_client_session_auth_status(const char * key,AUTH_STATUS status)
{
    return sessionMgr.set_session_auth_status(key,status);
}

/*
*session manager
*/
int SvrClient::close_client_session(char * key, int flag , uint64_t trans_size)
{
	  if(flag == TRUE)
	  {
		  sessionMgr.remove_session(key);
	  }
	  else
	  {
		  sessionMgr.set_session_active_status(key,false,trans_size);
	  }
      return SUCCESS;
}

/*
*add client session  to list
*/
int SvrClient::add_client_session(http_request_header * hrt,user_token * token)
{
    if(hrt == NULL || token == NULL)
         return FAILURE;

    int ret = FAILURE;
    session_node *  pclientNode = NULL;
    /*find session*/
    pclientNode = sessionMgr.find_session(token->key);
    if(pclientNode != NULL)
    {
        if(pclientNode->iauthcode != AUTH_DISCONN_WAIT
            && pclientNode->iauthcode != AUTH_FAILURE)
        {
            pclientNode->client_ip = token->remote_addr.sin_addr.s_addr;
            pclientNode->conn_status= true;
            pclientNode->last_conn_time = time(NULL);
            pclientNode->conn_count ++;
            pclientNode->conn_index = token->conn_index;
            return SUCCESS;
        }
        else
        {
        	pclientNode->conn_status = false;
            /*log ,check session status,not success*/
            this->pSvrlog->log_fmt(LOG_INFO,"[%s]add client session,check session status:%d",token->key,pclientNode->iauthcode);
        }
    }
    else
    {
        sessionMgr.alloc_node(&pclientNode);
        if(pclientNode == NULL)
            return FAILURE;

        memset(pclientNode->key,'\0',sizeof(pclientNode->key));
        strcpy(pclientNode->key,token->key);
        pclientNode->id = token->id ;
        pclientNode->iauthcode = AUTH_WAIT;
        pclientNode->connid = this->connid++;
        pclientNode->conn_count = 1;
        pclientNode->client_ip = token->remote_addr.sin_addr.s_addr;
        pclientNode->conn_status= true;
        pclientNode->total_trans_size = 0;
        pclientNode->connection_time = time(NULL);
        pclientNode->last_conn_time =  pclientNode->connection_time;
        pclientNode->conn_index = token->conn_index;
        memset(pclientNode->certificate,'\0',sizeof(pclientNode->certificate));

        /*struct auth url pars*/
        strcpy(pclientNode->certificate,hrt->pars);
        memset(pclientNode->request_content,'\0',sizeof(pclientNode->request_content));
        strcpy(pclientNode->request_content,hrt->file_name);
        pclientNode->request_content_hash_index = (long)utils::crc32_has_key((uchar *)pclientNode->request_content,strlen(pclientNode->request_content));

        /*
        *if add session true,add to auth,else do nothing ,because
        *the session mgr will free the pclientNode autoly,
        *do not free again.
        */
        if(sessionMgr.add_session(pclientNode))
        {
        	/*add to auth*/
			user_token * newtoken = NULL;
			this->alloc(&newtoken);
			newtoken->id = token->id;
			memset(newtoken->key,'\0',sizeof(newtoken->key));
			strcpy(newtoken->key,token->key);
			newtoken->type = CDN_AUTH_CLIENT;
			handle_lock.Lock();
			{
				handle_auth_list.push(newtoken);

				handle_lock.Unlock();
			}
			/*end*/

            ret =  SUCCESS;
        }
        else
        {
            /*log ,Add session not success*/
        	this->pSvrlog->log_fmt(LOG_INFO,"[%s]Add_session error!",token->key);
        }
    }

    return ret;
}

/*
*user force client session online
*/
int SvrClient::force_client_session_offline(const char * key)
{
    if(key == NULL)
        return FAILURE;

    int ret = FAILURE;
    session_node *  pclientNode = NULL;
    /*find session*/
    pclientNode = sessionMgr.find_session(key);
    /*session begin single enter*/
    sessionMgr.begin_enter();
    {
        if(pclientNode != NULL && pclientNode->iauthcode != AUTH_DISCONN_WAIT)
        {
        	/*set close flag*/
        	pclientNode->op_flag = SCLOSE;
			 /*end*/
            ret = SUCCESS;
        }
        /*session begin single exit*/
        sessionMgr.end_enter();
    }

    return ret;
}

/*
*force client list offline
*key,key,key...
*/
int SvrClient::force_client_list_offline(const char * keys)
{
    int count = 1;
    size_t index = 0,len = strlen(keys);
    char key[GUID_LEN];
    size_t split_index = 0;
    while(index < len)
    {
        if(keys[index] == ',')
        {
            if(index - split_index > 0)
            {
                memset(key,'\0',GUID_LEN);
                memcpy(key,keys + split_index,index - split_index);
                this->force_client_session_offline(key);
            }

            /*split next*/
            count ++;
            split_index = index + 1;
        }

        /*next*/
        index ++;
    }

    /*last close*/
    if(len - split_index > 0)
    {
       this->force_client_session_offline(keys + split_index);
    }


    /*end*/
    return count;
}

/*
 *clear_client_connect_by_request_content
 */
 int SvrClient::clear_client_connect_by_request_content(const char * fileName)
 {
	 if(fileName == NULL || strlen(fileName) == 0)
		 return 0;

     int count = 0;
     long file_hash_index = (long)utils::crc32_has_key((uchar *)fileName,strlen(fileName));
     /*do collect auth session ,and check timeout*/
     session_node * p_node = sessionMgr.begin_enter();
     {
         while(p_node != NULL)
         {
             if(p_node->iauthcode != AUTH_DISCONN_WAIT
                 && p_node->request_content_hash_index == file_hash_index
                 && strcmp(p_node->request_content,fileName) == 0)
             {
                 /*set close flag*/
                 p_node->op_flag = SCLOSE;
                 count ++;
                 /*end*/
             }

             /*next*/
             p_node= p_node->next;
         }

         /*must end enter*/
         sessionMgr.end_enter();
     }
     /*end*/
     return count;
 }

 /*
 *get count by session request content name
 */
 int SvrClient::get_count_by_request_content(const char * fileName)
 {
     int count = 0;
     long file_hash_index = utils::crc32_has_key((uchar *)fileName,strlen(fileName));
     /*do collect auth session ,and check timeout*/
     session_node * p_node = sessionMgr.begin_enter();
     {
         while(p_node != NULL)
         {
               if((p_node->request_content_hash_index == file_hash_index)
                 && (strcmp(p_node->request_content,fileName) == 0))
               {
                    count ++;
               }

               /*next*/
               p_node= p_node->next;
         }

         /*must end enter*/
         sessionMgr.end_enter();
     }

     /*end*/
     return count;
 }

/*
*clear_time_out_client_session
*/
int SvrClient::clear_time_out_client_session(void)
{
    int count = 0;
    /*do collect auth session ,and check timeout*/
    session_node * p_node = sessionMgr.begin_enter();
    {
        int nspan_time = 0;
        time_t timeCur = time(NULL);
        while(p_node != NULL)
        {
            /*check time out*/
            nspan_time = int(timeCur - p_node->last_conn_time);
            if(p_node->iauthcode != AUTH_DISCONN_WAIT
            		&& ( (!p_node->conn_status && nspan_time >= DEF_TIMEOUT)
            		   ||(p_node->conn_status && nspan_time > MAX_CONNTIME)
					   ||(p_node->op_flag == SCLOSE) ))
            {
                p_node->iauthcode = AUTH_DISCONN_WAIT;

                /*add to auth*/
			    user_token * newtoken = NULL;
			    this->alloc(&newtoken);
			    newtoken->id = p_node->id;
			    memset(newtoken->key,'\0',sizeof(newtoken->key));
			    strcpy(newtoken->key,p_node->key);
			    newtoken->type = CDN_AUTH_CLIENT;
			    handle_lock.Lock();
			    {
					   handle_auth_list.push(newtoken);
					   count ++;

					   handle_lock.Unlock();
			    }
			    /*end*/
            }

            /*next*/
            p_node= p_node->next;
        }

        /*must end enter*/
        sessionMgr.end_enter();
    }
    /*end*/
    return count;
}

/*
*alloc_request_header
*/
void SvrClient::alloc_request_header(http_request_header ** hrt)
{
    http_lock.Lock();
    {
        if(this->http_request_header_pool.size()>0)
        {
            *hrt = http_request_header_pool.top();
            http_request_header_pool.pop();
        }
        else
        {
            (*hrt) = new http_request_header();
        }
        http_lock.Unlock();
    }
}

/*
*free_request_header
*/
void SvrClient::free_request_header(http_request_header * hrt)
{
    http_lock.Lock();
    {
        if(hrt != NULL)
        {
            http_request_header_pool.push(hrt);
        }
        http_lock.Unlock();
    }
}

/*
*op buf alloc and free
*/
void SvrClient::alloc_op_buf(op_buf ** pbf)
{
    op_buf_lock.Lock();
    {
          if(this->op_buf_pool.size() > 0)
          {
              *pbf = op_buf_pool.top();
              op_buf_pool.pop();
          }
          else
          {
              *pbf = new op_buf();
              (*pbf)->buf = new ubyte[op_buf_len];
              (*pbf)->len = op_buf_len;
              memset((*pbf)->buf,'\0',op_buf_len);
          }
          op_buf_lock.Unlock();
    }
}

/*
*op buf alloc and free
*/
void SvrClient::free_op_buf(op_buf * pbf)
{
    op_buf_lock.Lock();
    {
        if(pbf != NULL)
        {
            memset(pbf->buf,'\0',op_buf_len);
            op_buf_pool.push(pbf);
        }
        op_buf_lock.Unlock();
    }
}

/*
*open request file
*/
bool SvrClient::open_request_file(http_request_header * hrt,user_token * token)
{
    if(strlen(this->pSvrconfig->rootpath) == 0 || hrt->file_name_len < 1)
    {
        pSvrlog->log_fmt(LOG_ERR,"root path or file_name is null");
        return false;
    }

    int retvalue  = false;
    /*transmit file name codes*/
    op_buf * m_src_code = NULL, * m_dest_code = NULL;
    this->alloc_op_buf(&m_src_code);
    this->alloc_op_buf(&m_dest_code);
    if(m_src_code == NULL || m_dest_code == NULL)
    {
        this->free_op_buf(m_src_code);
        this->free_op_buf(m_dest_code);
        m_src_code = NULL;
        m_dest_code = NULL;
        pSvrlog->log_fmt(LOG_ERR,"alloc op buf failure,open_request_file");
        return false;
    }

    /*get virtual path name */
	char * fptr = NULL;
	fptr = strstr(hrt->file_name + 1,"/");
	if(fptr != NULL)
	{
		m_src_code->len = fptr - hrt->file_name - 1;
		if(m_src_code->len > 0)
		{
			memcpy(m_src_code->buf,hrt->file_name + 1,m_src_code->len);
		}
	}
	/*get virtual direction*/
	bool ret = this->pSvrFileUtils->get_vir_dir((char *)m_src_code->buf,(char *)m_dest_code->buf,op_buf_len);
	/*get file name*/
	if(ret)
	{
		strcat((char *)m_dest_code->buf,fptr);
	}
	else
	{
		strcat((char *)m_dest_code->buf,hrt->file_name);
	}

    /*replace '\\' to '/' */
    size_t index = 0;
    size_t len = strlen((char *)m_dest_code->buf);
    while(index < len)
    {
        if((*(m_dest_code->buf+index)) == '\\')
                (*(m_dest_code->buf+index)) = '/';
        /*next char*/
        index++;
    }
    pSvrlog->log_fmt(LOG_INFO,"open file :%s\r\n",(char *)m_dest_code->buf);
     /*
    *open Linux file fd
    */
    token->filefd = this->pSvrFileUtils->open_file((char *)m_dest_code->buf,token->hFile_size);
    if(token->filefd >= 0 && token->hFile_size > 0)
    {
    	 retvalue = true;
    }

    /*free buf*/
    this->free_op_buf(m_src_code);
    this->free_op_buf(m_dest_code);
    m_src_code = NULL;
    m_dest_code = NULL;

    return retvalue;
}

/*
*decode file name
*/
bool SvrClient::decode_file_name(http_request_header * hrt,user_token * token)
{
    if(hrt == NULL || token == NULL)
         return false;

    /*begin check ,valid ,decode the filename*/
    unsigned int index = 0;
    char * pChar = _NULL;
    /*check is can decode*/
    pChar = strrchr(hrt->file_name,'.');
    if(pChar != NULL)
    {
        return false;
    }

    /*replace struct char to base64 char*/
    while(index <hrt->file_name_len)
    {
        if((*(hrt->file_name+index)) == '-')
                (*(hrt->file_name+index)) = '=';
        if((*(hrt->file_name+index)) == '^')
                (*(hrt->file_name+index)) = '/';
        if((*(hrt->file_name+index)) == '~')
                (*(hrt->file_name+index)) = '/';
        /*next char*/
        index++;
    }
    /*
    *now begin base64 decode
    */
    op_buf * m_src_code = NULL, * m_dest_code = NULL;
    this->alloc_op_buf(&m_src_code);
    this->alloc_op_buf(&m_dest_code);
    if(m_src_code == NULL || m_dest_code == NULL)
    {
        this->free_op_buf(m_src_code);
        this->free_op_buf(m_dest_code);
        m_src_code = NULL;
        m_dest_code = NULL;
        return false;
    }

    /*copy file name*/
    memcpy(m_src_code->buf,hrt->file_name,hrt->file_name_len);
    m_src_code->len = hrt->file_name_len;
    size_t ret_len =  utils::decode_base64(m_dest_code->buf,op_buf_len,m_src_code->buf,m_src_code->len);
    m_dest_code->len = ret_len;

    /*now begin url decode twice*/
    memset(m_src_code->buf,'\0',op_buf_len);
    m_src_code->len = 0;
    m_src_code->len = utils::url_decode(m_src_code->buf,op_buf_len,m_dest_code->buf,m_dest_code->len);

    memset(m_dest_code->buf,'\0',op_buf_len);
    m_dest_code->len = 0;
    m_dest_code->len = utils::url_decode(m_dest_code->buf,op_buf_len,m_src_code->buf,m_src_code->len);

    /*copy decode str to src args*/
    memset(hrt->file_name,'\0',hrt->file_name_len);
    memcpy(hrt->file_name,m_dest_code->buf,m_dest_code->len);

    /*free buf*/
    this->free_op_buf(m_src_code);
    this->free_op_buf(m_dest_code);
    m_src_code = NULL;
    m_dest_code = NULL;
    return true;

}

/*
*decode pars
*/
bool SvrClient::decode_pars(http_request_header * hrt,user_token * token)
{
    if(hrt == NULL || token == NULL)
        return false;

    bool ret =  false;
    /*get pars from file name*/
    if(hrt->pars_len == 0 && hrt->file_name_len > 64)
    {
        /*first,get pars*/
        char * ch_str = NULL;
        ch_str = strstr(hrt->file_name + 1,"/");
        if(ch_str != NULL)
        {
            hrt->pars_len = (size_t)(ch_str - hrt->file_name) - 1;
            if(hrt->pars_len > 0)
            {
                 memcpy(hrt->pars,hrt->file_name + 1 ,hrt->pars_len);
            }
        }
    }

    /*check pars format*/
    if(hrt->pars_len == 0)
    {
         return false;
    }

    /*replace struct char to base64 char*/
    unsigned int index = 0;
    while(index < hrt->pars_len)
    {
        if((*(hrt->pars+index)) == '-')
                (*(hrt->pars+index)) = '=';
        if((*(hrt->pars+index)) == '^')
                (*(hrt->pars+index)) = '/';
        if((*(hrt->pars+index)) == '~')
                       (*(hrt->pars+index)) = '/';
        /*next char*/
        index++;
    }
    /*now begin base64 decode*/
    op_buf * m_src_code = NULL, * m_dest_code = NULL;
    this->alloc_op_buf(&m_src_code);
    this->alloc_op_buf(&m_dest_code);
    if(m_src_code == NULL || m_dest_code == NULL)
    {
        this->free_op_buf(m_src_code);
        this->free_op_buf(m_dest_code);
        m_src_code = NULL;
        m_dest_code = NULL;
        return false;
    }

    /*copy pars*/
    memcpy(m_src_code->buf,hrt->pars,hrt->pars_len);
    m_src_code->len = hrt->pars_len;
    m_dest_code->len =  utils::decode_base64(m_dest_code->buf,op_buf_len,m_src_code->buf,m_src_code->len);

    /*get file name*/
    char * ch_str = NULL;
    ch_str = strstr((char *)m_dest_code->buf,"&file=");
    if(ch_str != NULL)
    {
        hrt->file_name_len =  m_dest_code->len - ((ubyte *)ch_str - m_dest_code->buf + 6);

        memset(hrt->file_name,'\0',MAX_REQ_PATH_LEN);
        memcpy(hrt->file_name,ch_str + 6,hrt->file_name_len);

        /*update pars*/
        m_dest_code->len -= 6 + hrt->file_name_len;
    }

    /*get session id*/
    ch_str = strstr((char *)m_dest_code->buf,"SessionID=");
    if(ch_str != NULL)
    {
        char * ch_end = NULL;
        ch_end =  strstr(ch_str,"&");
        if(ch_end != NULL)
        {
            size_t slen = ch_end - ch_str - 10;
            if(slen > 0  && slen < 64)
            {
                memcpy(token->key,ch_str + 10,slen);
                ret = true;
            }
        }
    }


    /*copy pars*/
    memset(hrt->pars,'\0',hrt->pars_len);
    memcpy(hrt->pars,m_dest_code->buf,m_dest_code->len);

    /*free buf*/
    this->free_op_buf(m_src_code);
    this->free_op_buf(m_dest_code);
    m_src_code = NULL;
    m_dest_code = NULL;

    /*return*/
    return ret;
}

/*
*decode administrator key
*/
bool SvrClient::decode_private_key(http_request_header * hrt)
{
    if(hrt == NULL)
          return false;

    if(hrt->privat_len == 0)
          return false;

    bool ret =  false;
    /*decode key*/
    op_buf * m_src_code = NULL, * m_dest_code = NULL;
    this->alloc_op_buf(&m_src_code);
    this->alloc_op_buf(&m_dest_code);
    if(m_src_code == NULL || m_dest_code == NULL)
    {
        this->free_op_buf(m_src_code);
        this->free_op_buf(m_dest_code);
        m_src_code = NULL;
        m_dest_code = NULL;
        return false;
    }

    /*replace struct char to base64 char*/
    unsigned int index = 0;
    while(index < hrt->privat_len)
    {
        if((*(hrt->privat+index)) == '-')
                (*(hrt->privat+index)) = '=';

        if((*(hrt->privat+index)) == '^')
                (*(hrt->privat+index)) = '/';

        if((*(hrt->privat+index)) == '~')
                (*(hrt->privat+index)) = '/';
        /*next char*/
        index++;
    }

    /*copy pars and base64 decode*/
    memcpy(m_src_code->buf,hrt->privat,hrt->privat_len);
    m_src_code->len = hrt->privat_len;
    m_dest_code->len =  utils::decode_base64(m_dest_code->buf,op_buf_len,m_src_code->buf,m_src_code->len);
    if(m_dest_code->len == 0)
    {
        this->free_op_buf(m_src_code);
        this->free_op_buf(m_dest_code);
        m_src_code = NULL;
        m_dest_code = NULL;
        return false;
    }

    /*3des decoder*/
    memset(m_src_code->buf,NULL,op_buf_len);
    m_src_code->len = des3_decrypt_default(m_dest_code->buf,m_dest_code->len,m_src_code->buf,op_buf_len);
    if(m_src_code->len == 0)
	{
		this->free_op_buf(m_src_code);
		this->free_op_buf(m_dest_code);
		m_src_code = NULL;
		m_dest_code = NULL;
		return false;
	}
    /*str trim*/
    int count = 0;
    for(size_t i = m_src_code->len -1 ;i > 0 ; i--)
    {
        int code = m_src_code->buf[i];
        if(code <= 32 || code >= 127)
        {
            count ++;
        }
        else
        {
            break;
        }
    }
    m_src_code->len -= count;
    /*copy key*/
    if(m_src_code->len > 0)
    {
        memset(hrt->privat,'\0',hrt->privat_len);
        memcpy(hrt->privat,m_src_code->buf,m_src_code->len);
        hrt->privat_len = m_src_code->len;
        ret = true;
    }

    /*free buf*/
    this->free_op_buf(m_src_code);
    this->free_op_buf(m_dest_code);
    m_src_code = NULL;
    m_dest_code = NULL;

    /*return*/
    return ret;

}

/*
*encode key
*/
bool SvrClient::encode_private_key(char * data, size_t data_len,size_t max_buf_len)
{
	if(data == NULL)
		return false;

	if(data_len == 0)
		return false;

	if(max_buf_len < data_len)
		return false;

	bool ret = false;
	/*encode key*/
	op_buf * m_src_code = NULL, * m_dest_code = NULL;
	this->alloc_op_buf(&m_src_code);
	this->alloc_op_buf(&m_dest_code);
	if(m_src_code == NULL || m_dest_code == NULL)
	{
		this->free_op_buf(m_src_code);
		this->free_op_buf(m_dest_code);
		m_src_code = NULL;
		m_dest_code = NULL;
		return false;
	}

	/*init*/
	memcpy(m_src_code->buf,data,data_len);
	m_src_code->len = data_len;

	/*first 3des*/
	m_dest_code->len = des3_encrypt_default(m_src_code->buf,m_src_code->len,m_dest_code->buf,op_buf_len);
	if(m_dest_code->len == 0)
	{
		this->free_op_buf(m_src_code);
		this->free_op_buf(m_dest_code);
		m_src_code = NULL;
		m_dest_code = NULL;
		return false;
	}

	/*second base64*/
	memset(m_src_code->buf,NULL,op_buf_len);
	m_src_code->len = 0;
	m_src_code->len = utils::encode_base64(m_src_code->buf,op_buf_len,m_dest_code->buf,m_dest_code->len);
	if(m_src_code->len == 0)
	{
		this->free_op_buf(m_src_code);
		this->free_op_buf(m_dest_code);
		m_src_code = NULL;
		m_dest_code = NULL;
		return false;
	}
	else
	{
		/*replace struct char to base64 char*/
		size_t index = 0;
		while(index < m_src_code->len)
		{
			if((*(m_src_code->buf+index)) == '=')
				(*(m_src_code->buf+index)) = '-';

			if((*(m_src_code->buf+index)) == '/')
				(*(m_src_code->buf+index)) = '~';

			/*next char*/
			index++;
		}

		/*copy*/
		memset(data,'\0',max_buf_len);
		memcpy(data,m_src_code->buf,m_src_code->len);
	}

	/*free buf*/
	this->free_op_buf(m_src_code);
	this->free_op_buf(m_dest_code);
	m_src_code = NULL;
	m_dest_code = NULL;

	/*return*/
	return ret;
}

/**
 * set request content offset
 */
void SvrClient::set_request_content_offset(http_request_header * hrt,user_token * token)
{
	/*request rang*/
	if(hrt->content_offset >= token->hFile_size)
	{
		hrt->content_offset = (token->hFile_size - 1);
	}

	if(hrt->content_end  >= token->hFile_size)
	{
		hrt->content_end = (token->hFile_size -1);
	}

	if(hrt->content_offset > 0 || hrt->content_end > 0)
	{
		token->hFile_offset = hrt->content_offset;

		if(hrt->content_end < hrt->content_offset)
		{
			 hrt->content_end = (token->hFile_size - 1);
		}

		token->trans_size = (hrt->content_end - hrt->content_offset + 1);
	}
	else if(hrt->is_have_rang) /*some request ,rang:bytes=0-*/
	{
		token->trans_size = token->hFile_size;
	}
}

/*
*check administrator operation cmd args
*/
Client_Type SvrClient::administrator_op_cmd(http_request_header *hrt)
{
    if(hrt == NULL)
        return INVALID_TYPE;

    Client_Type ret_type = HTTP_HTB_CLIENT;
    if(decode_private_key(hrt))
    {
        /*get closefile cmd line*/
        if(hrt->privat_len > 6 && memcmp(hrt->privat,"clear:", 6) == 0)
        {
              this->clear_client_connect_by_request_content(hrt->privat + 6);
        }
        else if(hrt->privat_len > 13 && memcmp(hrt->privat,"clear_delete:", 13) == 0)
		{
			int count = this->clear_client_connect_by_request_content(hrt->privat + 13);

			/*delete file*/
			this->pSvrFileUtils->add_deletefile(hrt->privat + 13,count);
		}
        else if(hrt->privat_len > 6 && memcmp(hrt->privat,"close:", 6) == 0)
        {
              this->force_client_list_offline(hrt->privat + 6);
        }
    }
    else
    {
        ret_type =  HTTP_ADMIN_CLIENT;
    }

    return ret_type;
}

/*
*get request type
*/
Client_Type SvrClient::anylsis_client_type(char * buf,size_t buf_len,user_token * token)
{
    if(buf == NULL || buf_len == 0 ||  token == NULL)
       return INVALID_TYPE;

    int ret = FAILURE;
    Client_Type ret_type = INVALID_TYPE;

    http_request_header *hrt = NULL;
    this->alloc_request_header(&hrt);
    int parsecode = 0;
    ret = http::parse_request_header(hrt,buf,buf_len,parsecode);
    if(ret != SUCCESS)
    {
    	if(parsecode == 1 && hrt->method != UNKNOW)
    	{
    		this->free_request_header(hrt);
    		return ON_RECV_TYPE;
    	}

        this->pSvrlog->log_fmt(LOG_ERR,"Parse_Request_Header_Error:%s\r\n",buf);
        this->free_request_header(hrt);
        return INVALID_TYPE;
    }

    /*
     * check is receive completed
     */
    if(hrt->header_len == 0)
    {
       this->free_request_header(hrt);
       return ON_RECV_TYPE;
    }

    /*
    *check file name
    */
    if(hrt->mime == NONE && hrt->file_name_len > 0 &&  hrt->pars_len >0)
    {
        if(decode_file_name(hrt,token))
        {
             hrt->mime = http::anlysis_mime_type(hrt);
        }
    }

    /*
    *check request type
    */
    if(hrt->mime == INFO)
    {
        ret_type = administrator_op_cmd(hrt);
        token->type = ret_type;
    }
    else if(hrt->mime == XML)
    {
        token->type = HTTP_BROWSE;
        ret_type =  HTTP_BROWSE;
    }
    else if(hrt->mime == HB)
	{
		if(!decode_pars(hrt,token))
		{
			this->free_request_header(hrt);
			return INVALID_TYPE;
		}

		this->sessionMgr.set_session_heartbeat(token->key);

		token->type = HTTP_HTB_CLIENT;
		ret_type =  HTTP_HTB_CLIENT;
	}
	else if(hrt->mime == SB)
	{
		if(!decode_pars(hrt,token))
		{
			this->free_request_header(hrt);
			return INVALID_TYPE;
		}

		this->force_client_session_offline(token->key);

		token->type = HTTP_HTB_CLIENT;
		ret_type =  HTTP_HTB_CLIENT;
	}
	else if(hrt->mime == ASPNET)
	{
		if(!decode_pars(hrt,token))
		{
			memset(token->key,'\0',sizeof(token->key));
			if(http::get_url_pars_value(hrt,"ConnectId=",token->key,64) == 0)
			{
				/*not find ConnectId*/
				this->free_request_header(hrt);
				return INVALID_TYPE;
			}
		}

		if(strcmp(hrt->file_name,"/ClientHeartbeat.aspx") == 0)
		{
			 this->sessionMgr.set_session_heartbeat(token->key);
		}
		else if(strcmp(hrt->file_name,"/UserLeave.aspx") == 0)
		{
			  this->force_client_session_offline(token->key);
		}

		token->type = HTTP_HTB_CLIENT;
		ret_type =  HTTP_HTB_CLIENT;
	}
    else if(hrt->mime < NONE)
    {
    	/*decode pars, and add session */
		if(!decode_pars(hrt,token))
		{
			this->pSvrlog->log_fmt(LOG_ERR,"[%s]decode_pars Error,FileName:%s\r\n",token->key,hrt->file_name);
			this->free_request_header(hrt);
			return INVALID_TYPE;
		}

		/**
		 * add to cdn auth
		 */
		if(this->add_client_session(hrt,token) == FAILURE)
		{
			this->pSvrlog->log_fmt(LOG_ERR,"[%s]add client session Error,FileName:%s\r\n",token->key,hrt->file_name);
			this->free_request_header(hrt);
			return INVALID_TYPE;
		}

        /*
         * set mime,and request rang
         **/
        token->fmt = hrt->mime;

        /*support url seek*/
        if(hrt->seek_offset > 0 && hrt->content_offset == 0)
        {
            hrt->content_offset = hrt->seek_offset;
        }

        /*
         * open file handle
         **/
        if(open_request_file(hrt,token))
        {
        	set_request_content_offset(hrt,token);
        }
        else
        {
        	/*
        	 * close session
        	 **/
        	this->close_client_session(token->key,FALSE,0);

            /*log:*/
            this->pSvrlog->log_fmt(LOG_ERR,"[%s]Open File Error,FileName:%s\r\n",token->key,hrt->file_name);
            this->free_request_header(hrt);
            return INVALID_TYPE;
        }

        /*
         * default download client request
         */
        token->type = PLAYER_CLIENT;
        ret_type =  PLAYER_CLIENT;
    }
    else
    {
    	/*check limt ip*/
		uint32_t downloadip = inet_addr(this->pSvrconfig->limit_ip);
		if(downloadip > 0 && downloadip != token->remote_addr.sin_addr.s_addr)
		{
			this->free_request_header(hrt);
			return INVALID_TYPE;
		}

		/*
		 * get real file name
		 * */
		char * pch = strrchr(hrt->file_name,'.');
		if((pch != NULL)  &&  (strcmp(pch,this->pSvrconfig->svr_key) == 0))
		{
			memset(pch,'\0',strlen(this->pSvrconfig->svr_key));
			http::anlysis_mime_type(hrt);
		}
		else
		{
			this->free_request_header(hrt);
			return INVALID_TYPE;
		}

    	/*
		 * set mime,and request rang
		 **/
    	token->fmt = hrt->mime;

		/*
		 * open file handle
		 **/
		if(open_request_file(hrt,token))
		{
			set_request_content_offset(hrt,token);
		}
		else
		{
			/*log:*/
			this->pSvrlog->log_fmt(LOG_ERR,"[%s]Open File Error,FileName:%s\r\n",token->key,hrt->file_name);
			this->free_request_header(hrt);
			return INVALID_TYPE;
		}

		/*
		 * default download client request
		 */
		token->type = DOWNLOAD_CLIENT;
		ret_type =  DOWNLOAD_CLIENT;
    }

    /*must free http request vars*/
    this->free_request_header(hrt);
    return ret_type;
}

/*
*get auth task
*/
user_token * SvrClient::get_next_session_auth_task(void)
{
    user_token * newtoken = NULL;
    handle_lock.Lock();
    {
        if(handle_auth_list.size() > 0)
        {
            newtoken = handle_auth_list.front();
            handle_auth_list.pop();
        }

        handle_lock.Unlock();
    }

    return newtoken;
}

/*
*struct_auth_request_data
*/
uint32_t SvrClient::struct_auth_request_data(char * buf,size_t buf_len,const char * key)
{
    if(buf == NULL || buf_len == 0 || key == NULL)
            return 0;

    uint32_t ret = 0;
    session_node * pClient = sessionMgr.find_session(key);
    if(pClient == NULL)
    {
    	return ret;
    }
	if(pClient->iauthcode != AUTH_WAIT
			&& pClient->iauthcode != AUTH_DISCONN_WAIT)
	{
		return ret;
	}

	/**
	* alloc op buf
	*/
	op_buf * m_src_code = NULL, * m_dest_code = NULL;
	this->alloc_op_buf(&m_src_code);
	this->alloc_op_buf(&m_dest_code);
	if(m_src_code == NULL || m_dest_code == NULL)
	{
		this->free_op_buf(m_src_code);
		this->free_op_buf(m_dest_code);
		m_src_code = NULL;
		m_dest_code = NULL;
		return ret;
	}

	/**
	*
	*struct auth pars
	*/
	m_src_code->len = utils::encode_base64(m_src_code->buf,op_buf_len,(ubyte *)pClient->certificate,strlen(pClient->certificate));
	/*replace struct char to base64 char*/
	unsigned int index = 0;
	while(index < m_src_code->len)
	{
		if((*(m_src_code->buf+index)) == '=')
				(*(m_src_code->buf+index)) = '-';
		if((*(m_src_code->buf+index)) == '/')
				(*(m_src_code->buf+index)) = '~';
		/*next char*/
		index++;
	}

	/**
	*
	* struct request header
	*/
	in_addr in;
	in.s_addr = pClient->client_ip;
	if(pClient->iauthcode == AUTH_WAIT)
	{
		sprintf((char *)m_dest_code->buf,"auth.aspx?pars=%s&connid=%d&userip=%s&randcode=%ld",(char *)m_src_code->buf, pClient->connid,inet_ntoa(in),(long)time(NULL));
		this->encode_private_key((char *)m_src_code->buf,m_src_code->len,op_buf_len);
		memmove(m_src_code->buf + 7,m_src_code->buf,strlen((char *)m_src_code->buf));
		memcpy(m_src_code->buf,"Mgsvr: ",7);
		ret = http::struct_request_header(buf,buf_len,(char *)m_dest_code->buf,pSvrconfig->auth_ip,(char *)m_src_code->buf,0,0);
	}
	else
	{
		long datasize = (long)(pClient->total_trans_size / 1024);
		sprintf((char *)m_dest_code->buf,"disauth.aspx?pars=%s&connid=%u&userip=%s&totalbytes=%ld&randcode=%ld",(char *)m_src_code->buf, pClient->connid,inet_ntoa(in),datasize,(long)time(NULL));
		this->encode_private_key((char *)m_src_code->buf,m_src_code->len,op_buf_len);
		memmove(m_src_code->buf + 7,m_src_code->buf,strlen((char *)m_src_code->buf));
		memcpy(m_src_code->buf,"Mgsvr: ",7);
		ret = http::struct_request_header(buf,buf_len,(char *)m_dest_code->buf,pSvrconfig->auth_ip,(char *)m_src_code->buf,0,0);
	}

	/**
	* free buf
	*/
	this->free_op_buf(m_src_code);
	this->free_op_buf(m_dest_code);
	m_src_code = NULL;
	m_dest_code = NULL;

	/**
	 * return
	 */
    return ret;
}

/*
*anylsis_auth_result
*/
AUTH_STATUS SvrClient::anylsis_auth_result(char * buf,size_t buf_len,const char * key)
{
    if(buf == NULL || key == NULL)
       return AUTH_FAILURE;

    session_node * pClient = sessionMgr.find_session(key);
    if(pClient == NULL)
    {
	   return AUTH_FAILURE;
    }
   	if(pClient->iauthcode != AUTH_WAIT && pClient->iauthcode != AUTH_DISCONN_WAIT)
   	{
   		return AUTH_FAILURE;
   	}
   	/**
   	 * anylsis_auth_result
   	 */
   	AUTH_STATUS authResult = AUTH_SUCCESS;
   	if(buf_len == 3)
   	{
		char ch_code[4];
		memset(ch_code,'\0',4);
		memcpy(ch_code,buf,3);
		int auth_code = atoi(ch_code);
		if(auth_code != 200)
		{
			authResult = AUTH_FAILURE;
			this->pSvrlog->log_save_db(LOG_INFO,"[%s] anylsis_auth_code:%d",key,auth_code);
		}
   	}

    /*set client session auth status*/
    if(pClient->iauthcode == AUTH_WAIT)
    {
    	this->sessionMgr.set_session_auth_status(key,authResult);
    	this->pSvrlog->log_save_db(LOG_INFO,"[%s] anylsis_auth_result:%d",key,authResult);
    }
    else
    {
    	this->close_client_session(pClient->key,TRUE);
    	this->pSvrlog->log_save_db(LOG_INFO,"[%s] remove session",key);
    }

    /*return result*/
    return authResult;
}

/*
*svr heartbeat function
*/
uint32_t SvrClient::struct_heartbeat_data(char * buf,size_t buf_len,int cur_session_count,int cur_connection_count)
{
	if(buf == NULL || buf_len == 0 || buf_len < 16)
	       return -1;

	size_t ret = 0;
	op_buf * m_src_code = NULL, * m_dest_code = NULL;
	this->alloc_op_buf(&m_src_code);
	this->alloc_op_buf(&m_dest_code);
	if(m_src_code == NULL || m_dest_code == NULL)
	{
		this->free_op_buf(m_src_code);
		this->free_op_buf(m_dest_code);
		m_src_code = NULL;
		m_dest_code = NULL;
		return ret;
	}

	sprintf((char *)m_src_code->buf,"heartbeat.aspx?type=xMediaServer&session_count=%d&connection_count=%d&vcode=%ld", cur_session_count, cur_connection_count, (long)time(NULL));
	sprintf((char *)m_dest_code->buf,"Mgsvr: %s",pSvrconfig->Svr_Name);
	char * ptr = (char *)m_dest_code->buf + 7;
	this->encode_private_key(ptr, strlen((char *)m_dest_code->buf) - 7 , op_buf_len - 7);
	ret = http::struct_request_header(buf,buf_len,(char *)m_src_code->buf,pSvrconfig->auth_ip,(char *)m_dest_code->buf,0,0);
	ptr = NULL;
    /**
	* free buf
	*/
	this->free_op_buf(m_src_code);
	this->free_op_buf(m_dest_code);
	m_src_code = NULL;
	m_dest_code = NULL;

	/**
	 * data len
	 */
	return ret;
}

/*
 * run
 */
void SvrClient::run(long useconds)
{
	/*
	*clear every 10 seconds
	*/
	if(this->SessionTick * useconds >= 10000000)
	{
		this->clear_time_out_client_session();
		this->SessionTick = 0;
	}

	/*time tick*/
	this->SessionTick ++;
}
